package com.demo.netty.handler;

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.*;
import io.netty.handler.ssl.SslHandler;
import io.netty.handler.stream.ChunkedFile;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Component;
import org.springframework.util.ResourceUtils;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.RandomAccessFile;

@Component
public class HttpRequestHandler extends SimpleChannelInboundHandler<FullHttpRequest> {
    private static final Logger logger = LoggerFactory.getLogger(HttpRequestHandler.class);
    
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) throws Exception {
        if (request.method() != HttpMethod.GET) {
            sendErrorResponse(ctx, HttpResponseStatus.METHOD_NOT_ALLOWED);
            return;
        }
        
        String uri = request.uri();
        logger.info("接收到HTTP请求: {}", uri);
        
        // 处理根路径，返回index.html
        if ("/".equals(uri) || "/index.html".equals(uri)) {
            serveStaticFile(ctx, request, "static/index.html");
            return;
        }
        
        // 处理其他静态资源
        if (uri.startsWith("/")) {
            serveStaticFile(ctx, request, "static" + uri);
            return;
        }
        
        // 未找到资源
        sendErrorResponse(ctx, HttpResponseStatus.NOT_FOUND);
    }
    
    private void serveStaticFile(ChannelHandlerContext ctx, FullHttpRequest request, String filePath) {
        try {
            // 获取项目根路径
            String rootPath = System.getProperty("user.dir");
            File file = new File(rootPath + "/src/main/resources/" + filePath);
            
            if (!file.exists()) {
                // 尝试从classpath获取
                ClassPathResource resource = new ClassPathResource(filePath);
                if (!resource.exists()) {
                    sendErrorResponse(ctx, HttpResponseStatus.NOT_FOUND);
                    return;
                }
                file = resource.getFile();
            }
            
            if (file.isHidden() || !file.isFile()) {
                sendErrorResponse(ctx, HttpResponseStatus.NOT_FOUND);
                return;
            }
            
            RandomAccessFile randomAccessFile = new RandomAccessFile(file, "r");
            long fileLength = randomAccessFile.length();
            
            HttpResponse response = new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK);
            response.headers().set(HttpHeaderNames.CONTENT_LENGTH, fileLength);
            
            // 根据文件扩展名设置Content-Type
            String contentType = getContentType(file.getName());
            response.headers().set(HttpHeaderNames.CONTENT_TYPE, contentType);
            
            // 检查是否需要保持连接
            boolean keepAlive = HttpUtil.isKeepAlive(request);
            if (!keepAlive) {
                response.headers().set(HttpHeaderNames.CONNECTION, HttpHeaderValues.CLOSE);
            } else if (request.protocolVersion().equals(HttpVersion.HTTP_1_1)) {
                response.headers().set(HttpHeaderNames.CONNECTION, HttpHeaderValues.KEEP_ALIVE);
            }
            
            ctx.write(response);
            
            // 写入文件内容
            if (ctx.pipeline().get(SslHandler.class) == null) {
                ctx.write(new ChunkedFile(randomAccessFile, 0, fileLength, 8192), 
                         ctx.newProgressivePromise());
            } else {
                ctx.write(new ChunkedFile(randomAccessFile, 0, fileLength, 8192));
            }
            
            // 结束响应
            ctx.writeAndFlush(LastHttpContent.EMPTY_LAST_CONTENT);
            
        } catch (Exception e) {
            logger.error("提供静态文件失败: {}", filePath, e);
            sendErrorResponse(ctx, HttpResponseStatus.INTERNAL_SERVER_ERROR);
        }
    }
    
    private String getContentType(String fileName) {
        if (fileName.endsWith(".html")) {
            return "text/html; charset=UTF-8";
        } else if (fileName.endsWith(".css")) {
            return "text/css; charset=UTF-8";
        } else if (fileName.endsWith(".js")) {
            return "application/javascript; charset=UTF-8";
        } else if (fileName.endsWith(".png")) {
            return "image/png";
        } else if (fileName.endsWith(".jpg") || fileName.endsWith(".jpeg")) {
            return "image/jpeg";
        } else if (fileName.endsWith(".gif")) {
            return "image/gif";
        } else {
            return "application/octet-stream";
        }
    }
    
    private void sendErrorResponse(ChannelHandlerContext ctx, HttpResponseStatus status) {
        FullHttpResponse response = new DefaultFullHttpResponse(
            HttpVersion.HTTP_1_1, status);
        response.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/plain; charset=UTF-8");
        ctx.writeAndFlush(response).addListener(io.netty.channel.ChannelFutureListener.CLOSE);
    }
    
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        logger.error("HTTP请求处理异常", cause);
        if (ctx.channel().isActive()) {
            sendErrorResponse(ctx, HttpResponseStatus.INTERNAL_SERVER_ERROR);
        }
    }
}